#ifndef SOCKET_UTIL_H
#define SOCKET_UTIL_H

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdexcept>
#include <string>

class SocketRAII{
public:
    SocketRAII(int fd):fd_(fd){}
    ~SocketRAII(){ if(fd_ > 0) close(fd_); }
    int get() const { return fd_; }
private:
    int fd_;
};

//设置非阻塞Socket
inline void set_nonblocking(int fd){
    int flags = fcntl(fd, F_GETFL, 0);
    if(flags == -1)
        throw std::runtime_error("fcntl F_GETFL failed");
    if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
        throw std::runtime_error("fcntl F_SETFL failed");
}

//创建并绑定服务器Socket
inline int create_server_socket(int port){
    int server_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    if(server_fd == -1)
        throw std::runtime_error("socket create failed");
    sockaddr_in address{};
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);
    
    int opt = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    if(bind(server_fd, (sockaddr*)&address, sizeof(address)) < 0)
        throw std::runtime_error("bind failed");

    if(listen(server_fd, 1000) < 0)
        throw std::runtime_error("listen failed");
    
    return server_fd;
}
#endif // SOCKET_UTIL_H